
local MODULE = {}
	MODULE.Name = "Aimbot"
	MODULE.Hooks = {}
	
// Variables
	local self = LocalPlayer()
	local tlist = {}
	local target = nil
	local fov = 5
	local update = 0
	
// Bones
	local bones = {
		"ValveBiped.Bip01_Neck1",
		"ValveBiped.Bip01_Spine4",
		"ValveBiped.Bip01_Spine2",
		"ValveBiped.Bip01_Spine1"
	}
	
// Prediction Numers
	local prediction = {
		weapon_pistol = 40000,
		weapon_357 = 20500,
		weapon_smg = 39000,
		weapon_ar2 = 39000,
		weapon_shotgun = 35000,
		weapon_crossbow = 3485,
		weapon_rpg = 0
	}
	
// Functions

	// Math Helping 
	
		local function Distance( a, b )
		
			return a:GetPos():Distance(b:GetPos())
			
		end
		
		local function Normal( ang )
		
			return math.abs(math.NormalizeAngle(ang))
			
		end
		
		local function Between( a, b, c )
			
			return ( a >= b and a <= c )
			
		end
		
	// Entity Helping
	
		local function GetBone( ent )
			
			if not ent:IsValid() then return end
			
			return ent:GetBonePosition( ent:LookupBone( bones[boneDefault]))
			
		end
		
		local function GetShootTrace( ent )
		
			local trace = {
				start = self:GetShootPos(),
				endpos = self:GetShootPos() + ( self:GetAimVector() * 163840 ),
				filter = { self }
			}
			
			return util.TraceLine( trace )
			
		end
		
		local function GetTrace( ent )
		
			local trace = {
				start = self:GetShootPos(),
				endpos = GetBone( ent ),
				filter = { self }
			}
			
			return ( util.TraceLine( trace ).Entity == ent or util.TraceLine( trace ).HitWorld )
			
		end
		
		local function Valid( ent )
		
			if not ent then return false end
		
			if not ent:IsValid() or ent == self or not ent:IsNPC() and not ent:IsPlayer() then return false end
			
			movetype = ent:GetMoveType()
			
			if movetype == MOVETYPE_NONE then return false end
			
			if ent:IsPlayer() then
			
				if not ent:Alive() or movetype == MOVETYPE_OBSERVER then return false end
				
			end
			
			return true
			
		end
		
// Main Functions
	
	function MODULE.AddToList( ent )
	
		if Valid( ent ) and not table.HasValue( tlist, ent ) then table.insert( tlist, ent ) end
		
	end
	
	function MODULE.Build()
		
		for k,v in pairs(ents.GetAll()) do
		
			MODULE.AddToList( v )
			
		end
		
	end
	
	function MODULE.Aim( UM )
	
		vangle = UM:GetViewAngles()
		
		if not aiming or not Valid( target ) then target = nil return end
		
		local bonepos = GetBone( target ) - self:GetShootPos()
		
		if predict then
		
			local pos = self:GetPos()
			local wep = self:GetActiveWeapon()
			local speed = pos:Distance(pos + self:GetVelocity())
			local dist = Distance( self, target )
			
			// Lets predict weapon shots!
			local plyV, targV = Vector( 0, 0, 0 ), Vector( 0, 0, 0 )
			
			if dist < 4000 and speed > 0 then plyV = self:GetVelocity() * dist / ( speed * dist * 0.125 ) end
			if wep:IsWeapon() and prediction[wep:GetClass()] != 0 then targV = target:GetVelocity() * distance / ( prediction[wep:GetClass()] or 150000 ) end
			
			bonepos = bonepos - plyV + targV
			
		end
		
		UM:SetViewAngles( bonepos:Angle())
		vangle = bonepos:Angle() 
		
	end
	
	function MODULE.Select()
	
		if not aiming or Valid( target ) then return end
		
		target = nil
		local ang = 0
		if #tlist == 0 or CurTime() >= update then 
		
			MODULE.Buld() 
			update = CurTime() + 0.1		
			
		end
		
		for k,v in pairs( tlist ) do
		
			if not ValidEntity( v ) then
			
				table.remove( tlist, k )
				
			elseif not target then
			
				ang = self:GetAimVector():Angle() - ( GetBone( v ) - self:GetShootPos() ):Angle()
				if Normal( ang.y ) < fov and Normal( ang.p ) < fov and GetTrace( ent ) then target = v end
				
			end
			
		end
		
	end
	
	function MODULE.View( ply, origin, ang, fov )
	
		local wep = self:GetActiveWeapon()
		
		if wep.Primary then wep.Primary.Recoil = 0 end
		
		return { origin = origin, angles = vangle, fov = fov }
		
	end
	
	function MODULE.Active()
		aiming = true
	end
	
	function MODULE.InActive()
		aiming = false
		target = nil
	end
	
// Register Module

	concommand.Add("+pab_bot", MODULE.Active)
	concommand.Add("-pab_bot", MODULE.InActive)
	
	--MODULE.Hooks[MODULE.View] = "CalcView"
	MODULE.Hooks[MODULE.Aim] = "CreateMove"
	MODULE.Hooks[MODULE.AddToList] = "OnEntityCreated"
	MODULE.Hooks[MODULE.Select] = "Think"
	PAB.Register( MODULE )